package ch.ffhs.ks.model;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Observable;

import javax.swing.table.DefaultTableModel;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;

import ch.ffhs.ks.mail.AccountInformationDownloader;
import ch.ffhs.ks.mail.MailDownloader;
import ch.ffhs.ks.mail.MailSender;
import ch.ffhs.ks.storage.StorageManager;

public class ModelContext extends Observable {

	private DefaultMutableTreeNode rootNode = new DefaultMutableTreeNode("Mail Client");
	private DefaultTreeModel treeModel = new DefaultTreeModel(rootNode);
	private MailsTableModel tableModel = new MailsTableModel();

	private MailConfiguration mailConfig;
	private Folder selectedFolder;
	private StorageManager storageManager;

	private HashMap<Folder, MailDownloader> activeMailDownloaders;

	public ModelContext(StorageManager storageManager)
	{
		tableModel.addColumn("Von");
		tableModel.addColumn("Betreff");
		tableModel.addColumn("Gesendet am");

		this.storageManager = storageManager;
		activeMailDownloaders = new HashMap<Folder, MailDownloader>();

	}

	public void loadConfiguration()
	{

		//MailConfiguration m = new MailConfiguration();
		//storageManager.saveConfiguration(m);

		mailConfig = storageManager.loadMailConfig();

		for(Account a : mailConfig.getAccounts())
		{
			AccountInformationDownloader aid = new AccountInformationDownloader(a, this);
			aid.execute();
		}

	}

	public void buildTree()
	{
		rootNode.removeAllChildren();

		for(Account account : mailConfig.getAccounts())
		{
			DefaultMutableTreeNode accountNode =  new DefaultMutableTreeNode();
			accountNode.setUserObject(account);

			for(Folder f : account.getFolders())
			{
				accountNode.add(f.getNode());
			}

			rootNode.add(accountNode);
		}

		treeModel.nodeStructureChanged(rootNode);
	}

	public void saveConfiguration()
	{
		storageManager.saveConfiguration(mailConfig);
	}

	public void treeViewSelectionChanged(Folder folder) {

		selectedFolder = folder;
		updateSelectedFoldersMails(false);
	}

	public void updateSelectedFoldersMails(boolean explicit)
	{

		updateTableModelWithSelectedFolder();

		if(selectedFolder != null && selectedFolder.isImapFolder() && (selectedFolder.needsRefresh() || explicit))
		{
			MailDownloader md = activeMailDownloaders.get(selectedFolder);

			if(md == null)
			{
				md = new MailDownloader(selectedFolder, this);

				activeMailDownloaders.put(selectedFolder, md);
				md.execute();
			}
		}
	}

	public void updateEmailModel(Folder folder)
	{
		if(folder.equals(selectedFolder))
		{
			updateTableModelWithSelectedFolder();
		}
	}

	private void updateTableModelWithSelectedFolder()
	{

		clearTableModel();
		if(selectedFolder != null)
		{
			for(Mail m : selectedFolder.getMails())
			{
				tableModel.addRow(m.getTableData());
			}
		}
	}

	public void clearTableModel()
	{
		for(int i = tableModel.getRowCount() -1; i >= 0; i--)
		{
			tableModel.removeRow(i);
		}

		System.out.println(tableModel.getRowCount());
	}

	public void mailDownloadCompleted(Folder folder)
	{
		if(activeMailDownloaders.containsKey(folder))
		{
			activeMailDownloaders.remove(folder);
		}

		saveConfiguration();
	}

	public ArrayList<Account> getAccounts()
	{
		return mailConfig.getAccounts();
	}

	public DefaultTreeModel getTreeModel()
	{
		return treeModel;
	}

	public DefaultTableModel getActualMails()
	{
		return tableModel;
	}

	public Mail getActualMailFromIndex(int i)
	{
		if(selectedFolder.getMails().size() > i && i >= 0)
		{
			return selectedFolder.getMails().get(i);
		}else
			return null;
	}

	public Account getSelectedAccount() {
		if(selectedFolder != null)
		{
			return selectedFolder.getAccount();
		}
		return null;
	}

	public void sendEmail(Mail newMail, Account account) {

		MailSender mailSender = new MailSender(newMail, account, this);
		mailSender.execute();

	}

	public void addNewSubfolder(String folderName) {

		Folder folder = new Folder(selectedFolder.getAccount(), folderName, false, selectedFolder);
		selectedFolder.addSubFolder(folder);

		saveConfiguration();

		buildTree();

	}

	public void moveMails(int[] selectedRows, Folder f) {

		for(int index = selectedRows.length-1; index >= 0; index--)
		{
			Mail m = selectedFolder.getMails().get(index);
			selectedFolder.getMails().remove(m);
			f.addMail(m);
		}

		saveConfiguration();
		updateTableModelWithSelectedFolder();
	}

	public Folder getSelectedFolder() {
		return selectedFolder;
	}

	public void deleteSelectedFolder() {

		ArrayList<Mail> mails = selectedFolder.getMails();

		selectedFolder.getMails().clear();

		Folder parent = selectedFolder.getParentFolder();
		parent.addMails(mails);

		parent.removeSubFolder(selectedFolder);

		buildTree();
		selectedFolder = parent;
		updateTableModelWithSelectedFolder();

		saveConfiguration();
	}

	public void updateEmailExplicit() {
		updateSelectedFoldersMails(true);
	}

	public void notifyProgress(String message)
	{
		setChanged();
		notifyObservers(message);
	}
}

